package entity

import (
	"bytes"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"
	"shqsoft.cn/pas3ui/base"
	"shqsoft.cn/pas3ui/popedom"
	"shqsoft.cn/pas3ui/popedom/entity"
)

// Position 职位
type Position struct {
	ID   int    `gorm:"primary_key;column:PONO"`
	Name string `gorm:"column:PONM;size:20"`
}

// TableName 职位表名
func (Position) TableName() string {
	return "T_USER_POSI"
}

// Serial 序列
type Serial struct {
	ID   int    `gorm:"primary_key;column:SENO"`
	Name string `gorm:"column:SENM;size:20"`
}

// TableName Serial 序列表名
func (Serial) TableName() string {
	return "T_USER_SERI"
}

// User 用户
type User struct {
	ID             int          `gorm:"AUTO_INCREMENT;primary_key;column:ID"`
	No             string       `gorm:"column:SysUserID;size:10"`
	OrganizationID *int         `gorm:"column:OrganID"`
	Organization   Organization `gorm:"ForeignKey:OrganizationID"`
	Name           string       `gorm:"column:SysUserName;size:20"`
	Memo           string       `gorm:"column:SysUserMemo;size:500"`
	EMail          string       `gorm:"column:EMail;size:60"`
	Telephone      string       `gorm:"column:Telephone;size:30"`
	PositionID     int          `gorm:"column:Position"`
	Position       Position     `gorm:"ForeignKey:PositionID"`
	SerialID       int          `gorm:"column:Serial"`
	Serial         Serial       `gorm:"ForeignKey:SerialID"`
	//Sex            string       `gorm:"column:SSEX;size:1"`
	Password      string     `gorm:"column:Password"`
	SexCaption    string     `gorm:"-"`
	IsPublic      int        `gorm:"column:ISPU"`
	RoleIds       string     `gorm:"column:RoleIds;size:100"`
	RoleCaptions  string     `gorm:"-"`
	Birthday      *time.Time `gorm:"column:Birthday;type:date;"`
	NameCaption   string     `gorm:"-"`
	STATUS        string     `gorm:"column:STATUS"`
	STATUSCaption string     `gorm:"-"`
	ISLSGHR       int        `gorm:"column:ISLSGHR"`
}

// TableName User用户表名
func (User) TableName() string {
	return "T_SysUser"
}

// BeforeCreate 插入前的触发器
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
	var count int64
	if u.OrganizationID == nil {
		err = tx.Raw(`select "ID" from T_Organization where "OrganName" =?`, u.Memo).Row().Scan(&u.OrganizationID)
		if err != nil {
			return
		}
		if u.OrganizationID == nil {
			info := fmt.Sprintf("部门%s不存在，请修改！", u.Memo)
			return errors.New(info)
		}
		err = tx.Raw(`select count(*) from "T_SysUser" where "SysUserID" =?`, u.No).Row().Scan(&count)
		if err != nil {
			return err
		}
		if count != 0 {
			info := fmt.Sprintf("员工号%s已存在，请修改员工号！", u.No)
			return errors.New(info)
		}
		//if u.Sex == "男" {
		//	u.Sex = "1"
		//} else {
		//	u.Sex = "2"
		//}
		u.STATUS = "1"
		u.PositionID = 7
		u.Password = popedom.HashPassword(u.No, "00000000")
		return
	} else {
		err = tx.Model(User{}).Where(`"SysUserID"=?`, u.No).Count(&count).Error
		if err != nil {
			return err
		}
		if count > 0 {
			info := fmt.Sprintf("员工号%s已存在，请修改！", u.No)
			return errors.New(info)
		}
		err = tx.Model(User{}).Where(`"SysUserName"=?`, u.Name).Count(&count).Error
		if err != nil {
			return err
		}
		if count > 0 {
			info := fmt.Sprintf("员工名称%s已存在，请修改！", u.No)
			return errors.New(info)
		}
		u.Password = popedom.HashPassword(u.No, "00000000")
	}
	return
}

// BeforeUpdate 默认员工不允许,有认定关系，不允许更改部门
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
	if u.ID == 0 {
		return errors.New("默认员工不允许修改！")
	}
	var oldUser User
	err = tx.First(&oldUser, u.ID).Error
	if err != nil {
		return err
	}
	if u.STATUS != "1" {
		u.Password = "password"
	} else if oldUser.Password == "password" {
		u.Password = popedom.HashPassword(u.No, "00000000")
	}
	if *u.OrganizationID == 216689 {
		u.Password = "password"
		return
	}
	if *u.OrganizationID != *oldUser.OrganizationID {
		msg, err := u.hasDivi(tx)
		if err != nil {
			return err
		}
		if msg != "" {
			return fmt.Errorf("%s，不能直接修改其所属部门，请使用员工调动功能！", msg)
		}
	}
	if u.No != oldUser.No {
		u.Password = popedom.HashPassword(u.No, "00000000")
	}
	err = base.CacheUser(u.ID, u.Name, *u.OrganizationID, u.No)
	if err != nil {
		return err
	}
	return
}

// BeforeDelete 有认定关系，不允许删除员工
func (u *User) BeforeDelete(tx *gorm.DB) (err error) {
	if u.ID == 0 {
		return errors.New("默认员工不允许删除！")
	}
	msg, err := u.hasDivi(tx)
	if err != nil {
		return err
	}
	if msg != "" {
		return fmt.Errorf("%s，不能删除！", msg)
	}
	return
}

func (u *User) hasDivi(tx *gorm.DB) (msg string, err error) {
	var count int
	row := tx.Raw(`select count(*) from "T_COMP_ACCO_DIVI" where "EMID"=?`, u.ID).Row()
	err = row.Scan(&count)
	if err != nil {
		return
	}
	if count > 0 {
		msg = "员工存在对公营销关系"
		return
	}
	row = tx.Raw(`select count(*) from "T_INDI_ACCO_DIVI" where "EMID"=?`, u.ID).Row()
	err = row.Scan(&count)
	if err != nil {
		return
	}
	if count > 0 {
		msg = "员工存在储蓄营销关系"
		return
	}
	row = tx.Raw(`select count(*) from "T_INDI_LOAN_DIVI" where "EMID"=?`, u.ID).Row()
	err = row.Scan(&count)
	if err != nil {
		return
	}
	if count > 0 {
		msg = "员工存在个贷营销关系"
		return
	}
	return
}

// AfterCreate 插入后的触发器
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
	err = base.CacheUser(u.ID, u.Name, *u.OrganizationID, u.No)
	if err != nil {
		return err
	}
	return
}

// AfterUpdate 修改后的触发器
func (u *User) AfterUpdate(tx *gorm.DB) (err error) {
	if u.RoleIds == "" {
		return
	}
	err = tx.Where(`"UserId" = ?`, u.ID).Delete(&(entity.UserRole{})).Error
	if err != nil {
		return err
	}
	var updateList entity.UserRole
	roleIds := strings.Split(u.RoleIds, ",")
	for _, roleID := range roleIds {
		updateList.UserId = &u.ID
		updateList.RoleId, _ = strconv.Atoi(roleID)
		err = tx.Model(entity.UserRole{}).Create(&updateList).Error
		if err != nil {
			return err
		}
	}
	err = popedom.ClearUserPermsFormRedis(u.ID)
	if err != nil {
		return err
	}
	err = popedom.LoadUserPermsToRedis(tx, u.ID)
	if err != nil {
		return err
	}
	return
}

// AfterFind 选择男女
func (u *User) AfterFind(tx *gorm.DB) (err error) {
	//if u.Sex == "1" {
	//	u.SexCaption = "男"
	//} else {
	//	u.SexCaption = "女"
	//}
	if u.STATUS == "1" {
		u.STATUSCaption = "正常"
	} else if u.STATUS == "2" {
		u.STATUSCaption = "已离职"
	} else {
		u.STATUSCaption = "暂停使用"
	}
	if u.RoleIds != "" {
		ids := strings.Split(u.RoleIds, ",")
		sql := `select "RoleName" from "t_Role" where "RoleId" in (?)`
		rows, err := base.MYDB.Raw(sql, ids).Rows()
		if err != nil {
			return err
		}
		var buff bytes.Buffer
		defer rows.Close()
		for rows.Next() {
			var caption string
			rows.Scan(&caption)
			buff.WriteString(caption)
			buff.WriteString(",")
		}
		if l := buff.Len(); l > 0 {
			buff.Truncate(l - 1)
		}
		u.RoleCaptions = buff.String()
	}
	u.NameCaption = u.Organization.Name + "-" + u.Name
	return
}

func (u *User) AfterDelete(tx *gorm.DB) (err error) {
	err = tx.Where(`"UserId" = ?`, u.ID).Delete(&(entity.UserRole{})).Error
	if err != nil {
		return err
	}
	return
}

// PositionEF 返回一个机构体
func PositionEF() base.EntityFunc {
	return func() interface{} {
		entity := Position{}
		return &entity
	}
}

// PositionESF 返回一个机构体数组
func PositionESF() base.EntitiesFunc {
	return func() interface{} {
		var entities []Position
		return &entities
	}
}
func SerialEF() base.EntityFunc {
	return func() interface{} {
		entity := Serial{}
		return &entity
	}
}
func SerialESF() base.EntitiesFunc {
	return func() interface{} {
		var entities []Serial
		return &entities
	}
}
func UserEF() base.EntityFunc {
	return func() interface{} {
		entity := User{}
		return &entity
	}
}
func UserESF() base.EntitiesFunc {
	return func() interface{} {
		var entities []User
		return &entities
	}
}

func init() {
	base.DaoPoolObj.Put("Position", base.NewDefaultDao(PositionEF(), PositionESF(), nil, "my"))
	base.DaoPoolObj.Put("Serial", base.NewDefaultDao(SerialEF(), SerialESF(), nil, "my"))
	relationship := []string{"Organization", "Position", "Serial"}
	base.DaoPoolObj.Put("User", base.NewDefaultDao(UserEF(), UserESF(), relationship, "my"))
}
